package com.xb.loan.usercenter.user.user.service.impl;

import com.xb.loan.log.exception.BizException;
import com.xb.loan.usercenter.service.user.IWinstantSessionService;
import com.xb.loan.usercenter.service.user.bean.WinstantLoginInfoVO;
import com.xb.loan.usercenter.service.user.bean.WinstantOnlineUserVO;
import com.xb.loan.usercenter.service.user.bean.WinstantUserSessionIdBakVO;
import com.xb.loan.usercenter.service.user.constant.UserConst;
import com.xb.loan.usercenter.user.util.PropertyConf;
import com.xb.loan.util.cache.DefaultCacheFactory;
import com.xb.loan.util.cache.redis.collection.RedisList;
import com.xb.loan.util.cache.redis.collection.Rlist;
import com.xb.loan.util.log.DefaultLoggerFacotry;
import com.xb.loan.util.log.LogFormatUtil;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.UUID;

@Service("winstantSessionService")
public class WinstantRedisSessionServiceImpl implements IWinstantSessionService {

    private static Logger logger = DefaultLoggerFacotry.getLogger(WinstantRedisSessionServiceImpl.class);
    
    private static final String ONLINE_USER_KEY = "WinstantOnlineUserVO";
    
    private static Rlist<String> onlineUserRList = new RedisList<String>("OnlineUser", String.class, true);
    
    @Autowired
	PropertyConf propertyConf;
    
	public boolean clearUserInfoCache(String sessionId) throws BizException {
		
		DefaultCacheFactory.getFacotry().getCache().removeBean(WinstantLoginInfoVO.class,sessionId);
		return true;
	}

	public boolean checkLogin(WinstantLoginInfoVO loginInfoVO) throws BizException {
		
		String userId = loginInfoVO.getUserId();
		Date tokenEffective = loginInfoVO.getTokenEffective();

		long lastAccessTime = tokenEffective.getTime();
		long currentTime = System.currentTimeMillis();
		
		logger.debug(LogFormatUtil.getFormatTemplate(new String[]{"用户","访问时间","当前时间"}),
				new Object[]{userId,new Date(lastAccessTime)+"-->"+lastAccessTime,new Date(currentTime)+"-->"+currentTime});
		if(lastAccessTime < currentTime){
			//不在有效期
			logger.info(LogFormatUtil.getFormatTemplate(new String[]{"用户","会话"}),
					new Object[]{userId,loginInfoVO.getSessionId()});
			return false;
		}
		//更新用户登录时间
		loginInfoVO.setLastAccessTime(new Date());
		this.updateUserInfoCache(loginInfoVO);
		return true;
	}
	
	public WinstantLoginInfoVO queryUserInfoCacheOnly(String sessionId) throws BizException {

		return DefaultCacheFactory.getFacotry().getCache().getBean(WinstantLoginInfoVO.class,sessionId);
	}
	
	public WinstantLoginInfoVO queryUserInfoCache(String sessionId) throws BizException {

		logger.debug(LogFormatUtil.getFormatTemplate(new String[]{"sessionId is "}),
				new Object[]{sessionId});
		WinstantLoginInfoVO loginInfoVO = this.queryUserInfoCacheOnly(sessionId);
		
		logger.debug(LogFormatUtil.getFormatTemplate(new String[]{"loginInfoVO is "}),
				new Object[]{loginInfoVO});
		if(loginInfoVO != null && checkLogin(loginInfoVO)){
			//在有效期
			return loginInfoVO;
		}
		return null;
	}

	public String insertUserInfoCache(WinstantLoginInfoVO loginInfoVO) throws BizException {
		
		//生成sessionId同时更新loginInfoVO
		generateSessionId(loginInfoVO);
		DefaultCacheFactory.getFacotry().getCache().setBean(WinstantLoginInfoVO.class,loginInfoVO.getSessionId(),loginInfoVO);
		//sessionId的记录列表
		onlineUserRList.add(loginInfoVO.getSessionId());
		//新增备份记录新的UserId和SessionId映射关系
		WinstantUserSessionIdBakVO userSessionIdBakVO = this.createUserSessionIdBakVO(loginInfoVO.getUserId(),
				loginInfoVO.getSessionId());
		this.insertUserSessionIdBakVO(userSessionIdBakVO);
		//更新在线用户数
		int realFlag = UserConst.UserRealFlag.NOREAL.getCode();
		if(loginInfoVO.getRealFlag() == UserConst.UserRealFlag.NOREAL.getCode()){
			
			realFlag = UserConst.UserRealFlag.NOREAL.getCode();
			logger.info(LogFormatUtil.getFormatMsg(new String[]{"module","userId","msg"},
					new String[]{"WinstantRedisSessionServiceImpl" ,loginInfoVO.getUserId(),"synUpdateOnlineUserVO NoRealCount will add 1!!!"}));
		}else{
			
			realFlag = UserConst.UserRealFlag.REAL.getCode();
			logger.info(LogFormatUtil.getFormatMsg(new String[]{"module","userId","msg"},
					new String[]{"WinstantRedisSessionServiceImpl" ,loginInfoVO.getUserId(),"synUpdateOnlineUserVO RealCount will add 1!!!"}));
		}
		this.synUpdateOnlineUserVO(realFlag, 1);
		return loginInfoVO.getSessionId();
	}
	
	public String insertUserInfoCacheOnly(WinstantLoginInfoVO loginInfoVO) throws BizException {
		
		//生成sessionId同时更新loginInfoVO
		generateSessionId(loginInfoVO);
		DefaultCacheFactory.getFacotry().getCache().setBean(WinstantLoginInfoVO.class,loginInfoVO.getSessionId(),loginInfoVO);
		return loginInfoVO.getSessionId();
	}

	public boolean updateUserInfoCache(WinstantLoginInfoVO loginInfoVO) throws BizException {
		
		DefaultCacheFactory.getFacotry().getCache().setBean(WinstantLoginInfoVO.class,loginInfoVO.getSessionId(),loginInfoVO);
		return true;
	}
	
	public String generateSessionId(WinstantLoginInfoVO loginInfoVO) throws BizException{
		String token = loginInfoVO.getToken();
		if(token != null && token.length() > 0){
			return token;
		}

		String prefix = new StringBuffer("")
					.append(new SimpleDateFormat("hhmmssSSS").format(new Date()) + "-")
					.append(new Random().nextInt(1000000)).toString();
		String uuidStr = prefix + "_" + UUID.randomUUID().toString();
		loginInfoVO.setSessionId(uuidStr);
		return uuidStr;
	}

	@Override
	public WinstantUserSessionIdBakVO queryUserSessionIdBakVO(String userId)
			throws BizException {

		return DefaultCacheFactory.getFacotry().getCache().getBean(WinstantUserSessionIdBakVO.class,userId);
	}

	@Override
	public boolean insertUserSessionIdBakVO(
			WinstantUserSessionIdBakVO userSessionIdBakVO) throws BizException {

		DefaultCacheFactory.getFacotry().getCache().setBean(WinstantUserSessionIdBakVO.class,userSessionIdBakVO.getUserId(),userSessionIdBakVO);
		return true;
	}

	@Override
	public boolean updatetUserSessionIdBakVO(
			WinstantUserSessionIdBakVO userSessionIdBakVO) throws BizException {

		DefaultCacheFactory.getFacotry().getCache().setBean(WinstantUserSessionIdBakVO.class,userSessionIdBakVO.getUserId(),userSessionIdBakVO);
		return true;
	}

	@Override
	public boolean clearUserSessionIdBakVO(String userId) throws BizException {

		DefaultCacheFactory.getFacotry().getCache().removeBean(WinstantUserSessionIdBakVO.class,userId);
		return true;
	}
	
	private WinstantUserSessionIdBakVO createUserSessionIdBakVO(String userId, String sessionId)throws BizException {
		
		WinstantUserSessionIdBakVO userSessionIdBakVO = new WinstantUserSessionIdBakVO();
		userSessionIdBakVO.setUserId(userId);
		userSessionIdBakVO.setSessionId(sessionId);
		userSessionIdBakVO.setLoginFailNum(0);
		userSessionIdBakVO.setLoginFailTime(null);
		if(propertyConf.getMaxLoginFailNum() != null){
			userSessionIdBakVO.setMaxLoginFailNum(propertyConf.getMaxLoginFailNum());
		}
		if(propertyConf.getMaxLoginFailTime() != null){
			userSessionIdBakVO.setMaxLoginFailTime(propertyConf.getMaxLoginFailTime());
		}
		return userSessionIdBakVO;
	}

	@Override
	public WinstantOnlineUserVO queryOnlineUserVO() throws BizException {
		
		return DefaultCacheFactory.getFacotry().getCache().getBean(WinstantOnlineUserVO.class,ONLINE_USER_KEY);
	}

	@Override
	public boolean insertOnlineUserVO(WinstantOnlineUserVO OnlineUserVO)
			throws BizException {
		
		DefaultCacheFactory.getFacotry().getCache().setBean(WinstantOnlineUserVO.class,ONLINE_USER_KEY,OnlineUserVO);
		return true;
	}

	@Override
	public synchronized boolean updateOnlineUserVO(WinstantOnlineUserVO OnlineUserVO)
			throws BizException {

		DefaultCacheFactory.getFacotry().getCache().setBean(WinstantOnlineUserVO.class,ONLINE_USER_KEY,OnlineUserVO);
		return true;
	}

	@Override
	public boolean clearOnlineUserVO() throws BizException {

		DefaultCacheFactory.getFacotry().getCache().removeBean(WinstantOnlineUserVO.class,ONLINE_USER_KEY);
		return true;
	}

	@Override
	public synchronized boolean synUpdateOnlineUserVO(int realFlag,int updateNum) throws BizException {
		
		WinstantOnlineUserVO onlineUserVO = this.queryOnlineUserVO();
		if(onlineUserVO == null){
			onlineUserVO = new WinstantOnlineUserVO();
		}
		
		if(realFlag == UserConst.UserRealFlag.NOREAL.getCode()){
			
			if((onlineUserVO.getNoRealCount() + updateNum)>=0){
				onlineUserVO.setNoRealCount(onlineUserVO.getNoRealCount() + updateNum);
			}
		}else{
			if((onlineUserVO.getRealCount() + updateNum)>=0){
				onlineUserVO.setRealCount(onlineUserVO.getRealCount() + updateNum);
			}
		}
		
		this.updateOnlineUserVO(onlineUserVO);
			
		return true;
	}

}
